home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / awt / TextComponent.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  18.2 KB  |  572 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)TextComponent.java    1.48 98/08/31
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.awt.peer.TextComponentPeer;
  17. import java.awt.event.*;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21. import sun.awt.SunToolkit;
  22.  
  23.  
  24. /**
  25.  * The <code>TextComponent</code> class is the superclass of 
  26.  * any component that allows the editing of some text. 
  27.  * <p>
  28.  * A text component embodies a string of text.  The 
  29.  * <code>TextComponent</code> class defines a set of methods 
  30.  * that determine whether or not this text is editable. If the
  31.  * component is editable, it defines another set of methods
  32.  * that supports a text insertion caret. 
  33.  * <p>
  34.  * In addition, the class defines methods that are used 
  35.  * to maintain a current <em>selection</em> from the text. 
  36.  * The text selection, a substring of the component's text, 
  37.  * is the target of editing operations. It is also referred
  38.  * to as the <em>selected text</em>.
  39.  *
  40.  * @version    1.44, 08/11/98
  41.  * @author     Sami Shaio
  42.  * @author     Arthur van Hoff
  43.  * @since       JDK1.0
  44.  */
  45. public class TextComponent extends Component {
  46.  
  47.     /**
  48.      * The value of the text.
  49.      * A null value is the same as "".
  50.      *
  51.      * @serial
  52.      * @see setText()
  53.      * @see getText()
  54.      */
  55.     String text;
  56.  
  57.     /**
  58.      * A boolean indicating whether or not this TextComponent is editable.
  59.      * It will be <code>true</code> if the text componet
  60.      * is editable and <code>false</code> if not.
  61.      *
  62.      * @serial
  63.      * @see isEditable()
  64.      */
  65.     boolean editable = true;
  66.  
  67.     /**
  68.      * The selection refers to the selected text, and the selectionStart
  69.      * is the start position of the selected text.
  70.      *
  71.      * @serial
  72.      * @see getSelectionStart()
  73.      * @see setSelectionStart()
  74.      */
  75.     int selectionStart;
  76.  
  77.     /**
  78.      * The selection refers to the selected text, and the selectionEnd
  79.      * is the end position of the selected text.
  80.      *
  81.      * @serial
  82.      * @see getSelectionEnd()
  83.      * @see setSelectionEnd()
  84.      */
  85.     int selectionEnd;
  86.  
  87.     /**
  88.      * true if this TextComponent has access to the System clipboard
  89.      */
  90.     transient private boolean canAccessClipboard;
  91.  
  92.     transient protected TextListener textListener;
  93.  
  94.     /*
  95.      * JDK 1.1 serialVersionUID 
  96.      */
  97.     private static final long serialVersionUID = -2214773872412987419L;
  98.  
  99.     /**
  100.      * Constructs a new text component initialized with the 
  101.      * specified text. Sets the value of the cursor to 
  102.      * <code>Cursor.TEXT_CURSOR</code>.
  103.      * @param      text the initial text that the component presents.
  104.      * @see        java.awt.Cursor
  105.      */
  106.     TextComponent(String text) {
  107.     this.text = (text != null) ? text : "";
  108.     setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
  109.     enableInputMethodsIfNecessary();
  110.     checkSystemClipboardAccess();
  111.     }
  112.  
  113.     private void enableInputMethodsIfNecessary() {
  114.     try {
  115.             Toolkit toolkit = Toolkit.getDefaultToolkit();
  116.             enableInputMethods(((SunToolkit) toolkit).enableInputMethodsForTextComponent());
  117.         } catch (Exception e) {
  118.             // if something bad happens, just don't enable input methods
  119.     }
  120.     }
  121.  
  122.     boolean areInputMethodsEnabled() {
  123.         // TextComponent handles key events without touching the eventMask or
  124.         // having a key listener, so just check whether the flag is set
  125.         return (eventMask & AWTEvent.INPUT_METHODS_ENABLED_MASK) != 0;
  126.     }
  127.  
  128.     /**
  129.      * Removes the TextComponent's peer.  The peer allows us to modify
  130.      * the appearance of the TextComponent without changing its
  131.      * functionality.
  132.      */
  133.     public void removeNotify() {
  134.         synchronized (getTreeLock()) {
  135.         TextComponentPeer peer = (TextComponentPeer)this.peer;
  136.         if (peer != null) {
  137.             text = peer.getText();
  138.         selectionStart = peer.getSelectionStart();
  139.         selectionEnd = peer.getSelectionEnd();
  140.         }
  141.         super.removeNotify();
  142.     }
  143.     }
  144.  
  145.     /**
  146.      * Sets the text that is presented by this 
  147.      * text component to be the specified text. 
  148.      * @param       t   the new text.
  149.      *                  If this parameter is <code>null</code> then
  150.      *                  the text is set to the empty  string "".
  151.      * @see         java.awt.TextComponent#getText  
  152.      */
  153.     public synchronized void setText(String t) {
  154.     text = (t != null) ? t : "";
  155.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  156.     if (peer != null) {
  157.         peer.setText(text);
  158.     }
  159.     }
  160.  
  161.     /**
  162.      * Gets the text that is presented by this text component.
  163.      * @see     java.awt.TextComponent#setText
  164.      */
  165.     public synchronized String getText() {
  166.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  167.     if (peer != null) {
  168.         text = peer.getText();
  169.     }
  170.     return text;
  171.     }
  172.  
  173.     /**
  174.      * Gets the selected text from the text that is
  175.      * presented by this text component.  
  176.      * @return      the selected text of this text component.
  177.      * @see         java.awt.TextComponent#select
  178.      */
  179.     public synchronized String getSelectedText() {
  180.     return getText().substring(getSelectionStart(), getSelectionEnd());
  181.     }
  182.  
  183.     /**
  184.      * Indicates whether or not this text component is editable.
  185.      * @return     <code>true</code> if this text component is
  186.      *                  editable; <code>false</code> otherwise.
  187.      * @see        java.awt.TextComponent#setEditable
  188.      * @since      JDK1ble
  189.      */
  190.     public boolean isEditable() {
  191.     return editable;
  192.     }
  193.  
  194.     /**
  195.      * Sets the flag that determines whether or not this
  196.      * text component is editable.
  197.      * <p>
  198.      * If the flag is set to <code>true</code>, this text component 
  199.      * becomes user editable. If the flag is set to <code>false</code>, 
  200.      * the user cannot change the text of this text component. 
  201.      * @param     t   a flag indicating whether this text component 
  202.      *                      should be user editable.
  203.      * @see       java.awt.TextComponent#isEditable
  204.      */
  205.     public synchronized void setEditable(boolean b) {
  206.     editable = b;
  207.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  208.     if (peer != null) {
  209.         peer.setEditable(b);
  210.     }
  211.     }
  212.  
  213.     /**
  214.      * Gets the start position of the selected text in 
  215.      * this text component. 
  216.      * @return      the start position of the selected text. 
  217.      * @see         java.awt.TextComponent#setSelectionStart
  218.      * @see         java.awt.TextComponent#getSelectionEnd
  219.      */
  220.     public synchronized int getSelectionStart() {
  221.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  222.     if (peer != null) {
  223.         selectionStart = peer.getSelectionStart();
  224.     }
  225.     return selectionStart;
  226.     }
  227.  
  228.     /**
  229.      * Sets the selection start for this text component to  
  230.      * the specified position. The new start point is constrained 
  231.      * to be at or before the current selection end. It also
  232.      * cannot be set to less than zero, the beginning of the 
  233.      * component's text.
  234.      * If the caller supplies a value for <code>selectionStart</code>
  235.      * that is out of bounds, the method enforces these constraints
  236.      * silently, and without failure.
  237.      * @param       selectionStart   the start position of the 
  238.      *                        selected text.
  239.      * @see         java.awt.TextComponent#getSelectionStart
  240.      * @see         java.awt.TextComponent#setSelectionEnd
  241.      * @since       JDK1.1
  242.      */
  243.     public synchronized void setSelectionStart(int selectionStart) {
  244.     /* Route through select method to enforce consistent policy
  245.          * between selectionStart and selectionEnd.
  246.          */
  247.     select(selectionStart, getSelectionEnd());
  248.     }
  249.  
  250.     /**
  251.      * Gets the end position of the selected text in 
  252.      * this text component. 
  253.      * @return      the end position of the selected text. 
  254.      * @see         java.awt.TextComponent#setSelectionEnd
  255.      * @see         java.awt.TextComponent#getSelectionStart
  256.      */
  257.     public synchronized int getSelectionEnd() {
  258.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  259.     if (peer != null) {
  260.         selectionEnd = peer.getSelectionEnd();
  261.     }
  262.     return selectionEnd;
  263.     }
  264.  
  265.     /**
  266.      * Sets the selection end for this text component to  
  267.      * the specified position. The new end point is constrained 
  268.      * to be at or after the current selection start. It also
  269.      * cannot be set beyond the end of the component's text.
  270.      * If the caller supplies a value for <code>selectionEnd</code>
  271.      * that is out of bounds, the method enforces these constraints
  272.      * silently, and without failure.
  273.      * @param       selectionEnd   the end position of the 
  274.      *                        selected text.
  275.      * @see         java.awt.TextComponent#getSelectionEnd
  276.      * @see         java.awt.TextComponent#setSelectionStart
  277.      * @since       JDK1.1
  278.      */
  279.     public synchronized void setSelectionEnd(int selectionEnd) {
  280.     /* Route through select method to enforce consistent policy
  281.          * between selectionStart and selectionEnd.
  282.          */
  283.     select(getSelectionStart(), selectionEnd);
  284.     }
  285.     
  286.     /**
  287.      * Selects the text between the specified start and end positions.
  288.      * <p>
  289.      * This method sets the start and end positions of the 
  290.      * selected text, enforcing the restriction that the start position 
  291.      * must be greater than or equal to zero.  The end position must be 
  292.      * greater than or equal to the start position, and less than or 
  293.      * equal to the length of the text component's text.  The 
  294.      * character positions are indexed starting with zero.  
  295.      * The length of the selection is endPosition-startPosition, so the 
  296.      * character at endPosition is not selected.  
  297.      * If the start and end positions of the selected text are equal,  
  298.      * all text is deselected.   
  299.      * If the caller supplies values that are inconsistent or out of 
  300.      * bounds, the method enforces these constraints silently, and 
  301.      * without failure.
  302.      * @param        selectionStart the zero-based index of the first 
  303.                        character to be selected.  
  304.      * @param        selectionEnd the zero-based end position of the 
  305.                        text to be selected. The character at 
  306.                        selectionEnd is not selected. 
  307.      * @see          java.awt.TextComponent#setSelectionStart
  308.      * @see          java.awt.TextComponent#setSelectionEnd
  309.      * @see          java.awt.TextComponent#selectAll
  310.      */
  311.     public synchronized void select(int selectionStart, int selectionEnd) {
  312.     String text = getText();
  313.     if (selectionStart < 0) {
  314.         selectionStart = 0;
  315.     }
  316.     if (selectionStart > text.length()) {
  317.         selectionStart = text.length();
  318.     }
  319.     if (selectionEnd > text.length()) {
  320.         selectionEnd = text.length();
  321.     }
  322.     if (selectionEnd < selectionStart) {
  323.         selectionEnd = selectionStart;
  324.     }
  325.  
  326.     this.selectionStart = selectionStart;
  327.     this.selectionEnd = selectionEnd;
  328.  
  329.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  330.     if (peer != null) {
  331.         peer.select(selectionStart, selectionEnd);
  332.     }
  333.     }
  334.  
  335.     /**
  336.      * Selects all the text in this text component.
  337.      * @see        java.awt.TextComponent@select
  338.      */
  339.     public synchronized void selectAll() {
  340.     String text = getText();
  341.     this.selectionStart = 0;
  342.     this.selectionEnd = getText().length();
  343.  
  344.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  345.     if (peer != null) {
  346.         peer.select(selectionStart, selectionEnd);
  347.     }
  348.     }
  349.  
  350.     /**
  351.      * Sets the position of the text insertion caret for 
  352.      * this text component.
  353.      * 
  354.      * @param        position the position of the text insertion caret.
  355.      * @exception    IllegalArgumentException if the value supplied
  356.      *                   for <code>position</code> is less than zero.
  357.      * @since        JDK1.1
  358.      */
  359.     public synchronized void setCaretPosition(int position) {
  360.     if (position < 0) {
  361.         throw new IllegalArgumentException("position less than zero.");
  362.     }
  363.  
  364.     int maxposition = getText().length();
  365.     if (position > maxposition) {
  366.         position = maxposition;
  367.     }
  368.  
  369.     TextComponentPeer peer = (TextComponentPeer)this.peer;
  370.     if (peer != null) {
  371.         peer.setCaretPosition(position);
  372.     } else {
  373.         throw new IllegalComponentStateException("Cannot set caret position until after the peer has been created");
  374.     }
  375.     }
  376.  
  377.     /**
  378.      * Gets the position of the text insertion caret for 
  379.      * this text component.
  380.      * @return       the position of the text insertion caret.
  381.      * @since        JDK1.1
  382.      */
  383.     public synchronized int getCaretPosition() {
  384.         TextComponentPeer peer = (TextComponentPeer)this.peer;
  385.     int position = 0;
  386.  
  387.     if (peer != null) {
  388.         position = peer.getCaretPosition();
  389.     } 
  390.     return position;
  391.     }
  392.  
  393.     /**
  394.      * Adds the specified text event listener to recieve text events 
  395.      * from this textcomponent.
  396.      * If l is null, no exception is thrown and no action is performed.
  397.      *
  398.      * @param l the text event listener
  399.      */ 
  400.     public synchronized void addTextListener(TextListener l) {
  401.     if (l == null) {
  402.         return;
  403.     }
  404.     textListener = AWTEventMulticaster.add(textListener, l);
  405.         newEventsOnly = true;
  406.     }
  407.  
  408.     /**
  409.      * Removes the specified text event listener so that it no longer
  410.      * receives text events from this textcomponent
  411.      * If l is null, no exception is thrown and no action is performed.
  412.      *
  413.      * @param             l     the text listener.
  414.      * @see               java.awt.event.TextListener
  415.      * @see               java.awt.Button#addTextListener
  416.      * @since             JDK1.1
  417.      */
  418.     public synchronized void removeTextListener(TextListener l) {
  419.     if (l == null) {
  420.         return;
  421.     }
  422.     textListener = AWTEventMulticaster.remove(textListener, l);
  423.     }
  424.  
  425.     // REMIND: remove when filtering is done at lower level
  426.     boolean eventEnabled(AWTEvent e) {
  427.         if (e.id == TextEvent.TEXT_VALUE_CHANGED) {
  428.             if ((eventMask & AWTEvent.TEXT_EVENT_MASK) != 0 ||
  429.                 textListener != null) {
  430.                 return true;
  431.             } 
  432.             return false;
  433.         }
  434.         return super.eventEnabled(e);
  435.     }     
  436.  
  437.     /**
  438.      * Processes events on this textcomponent. If the event is a
  439.      * TextEvent, it invokes the processTextEvent method,
  440.      * else it invokes its superclass's processEvent.
  441.      * @param e the event
  442.      */
  443.     protected void processEvent(AWTEvent e) {
  444.         if (e instanceof TextEvent) {
  445.             processTextEvent((TextEvent)e);
  446.             return;
  447.         }
  448.     super.processEvent(e);
  449.     }
  450.  
  451.     /** 
  452.      * Processes text events occurring on this text component by
  453.      * dispatching them to any registered TextListener objects.
  454.      * NOTE: This method will not be called unless text events
  455.      * are enabled for this component; this happens when one of the
  456.      * following occurs:
  457.      * a) A TextListener object is registered via addTextListener()
  458.      * b) Text events are enabled via enableEvents()
  459.      * @see Component#enableEvents
  460.      * @param e the text event
  461.      */ 
  462.     protected void processTextEvent(TextEvent e) {
  463.         if (textListener != null) {
  464.             int id = e.getID();
  465.         switch (id) {
  466.         case TextEvent.TEXT_VALUE_CHANGED:
  467.         textListener.textValueChanged(e);
  468.         break;
  469.         }
  470.         }
  471.     }
  472.  
  473.     /**
  474.      * Returns the parameter string representing the state of this text 
  475.      * component. This string is useful for debugging. 
  476.      * @return      the parameter string of this text component.
  477.      */
  478.     protected String paramString() {
  479.     String str = super.paramString() + ",text=" + getText();
  480.     if (editable) {
  481.         str += ",editable";
  482.     }
  483.     return str + ",selection=" + getSelectionStart() + "-" + getSelectionEnd();
  484.     }
  485.  
  486.     /**
  487.      * Assigns a valid value to the canAccessClipboard instance variable.
  488.      */
  489.     private void checkSystemClipboardAccess() {
  490.         canAccessClipboard = true;
  491.     SecurityManager sm = System.getSecurityManager();
  492.     if (sm != null) {
  493.         try {
  494.             sm.checkSystemClipboardAccess();
  495.         }
  496.         catch (SecurityException e) {
  497.             canAccessClipboard = false;
  498.         }
  499.     }
  500.     }
  501.  
  502.     /* 
  503.      * Serialization support.  Since the value of the fields
  504.      * selectionStart, and selectionEnd, and text aren't neccessarily
  505.      * up to date we sync them up with the peer before serializing.
  506.      */
  507.     /**
  508.      * The textComponent SerializedDataVersion.
  509.      *
  510.      * @serial
  511.      */
  512.     private int textComponentSerializedDataVersion = 1;
  513.  
  514.     /**
  515.      * Writes default serializable fields to stream.  Writes
  516.      * a list of serializable ItemListener(s) as optional data.
  517.      * The non-serializable ItemListner(s) are detected and
  518.      * no attempt is made to serialize them.
  519.      *
  520.      * @serialData Null terminated sequence of 0 or more pairs.
  521.      *             The pair consists of a String and Object.
  522.      *             The String indicates the type of object and
  523.      *             is one of the following :
  524.      *             itemListenerK indicating and ItemListener object.
  525.      *
  526.      * @see AWTEventMulticaster.save(ObjectOutputStream, String, EventListener)
  527.      * @see java.awt.Component.itemListenerK
  528.      */
  529.     private void writeObject(java.io.ObjectOutputStream s)
  530.       throws java.io.IOException 
  531.     {
  532.       TextComponentPeer peer = (TextComponentPeer)this.peer;
  533.       if (peer != null) {
  534.     text = peer.getText();
  535.     selectionStart = peer.getSelectionStart();
  536.     selectionEnd = peer.getSelectionEnd();
  537.       }
  538.       s.defaultWriteObject();
  539.  
  540.       AWTEventMulticaster.save(s, textListenerK, textListener);
  541.       s.writeObject(null);
  542.     }
  543.  
  544.     /**
  545.      * Read the ObjectInputStream and if it isnt null
  546.      * add a listener to receive item events fired
  547.      * by the TextComponent.
  548.      * Unrecognised keys or values will be Ignored.
  549.      * 
  550.      * @see removeActionListener()
  551.      * @see addActionListener()
  552.      */
  553.     private void readObject(ObjectInputStream s)
  554.         throws ClassNotFoundException, IOException 
  555.     {
  556.         s.defaultReadObject();
  557.  
  558.         Object keyOrNull;
  559.         while(null != (keyOrNull = s.readObject())) {
  560.         String key = ((String)keyOrNull).intern();
  561.  
  562.         if (textListenerK == key) 
  563.             addTextListener((TextListener)(s.readObject()));
  564.  
  565.         else // skip value for unrecognized key
  566.             s.readObject();
  567.         }
  568.     enableInputMethodsIfNecessary();
  569.     checkSystemClipboardAccess();
  570.     }
  571. }
  572.